package com.yhsoft.wxprogram.controller;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import com.yhsoft.buyer.entity.BuyerOrder;
import com.yhsoft.buyer.service.IBuyerOrderService;
import com.yhsoft.buyer.service.IBuyerPaymentService;
import com.yhsoft.common.vo.Result;
import com.yhsoft.wxprogram.controller.request.FlkPayInVo;
import com.yhsoft.wxprogram.controller.response.FLKPayOutVo;
import com.yhsoft.wxprogram.dto.WxChatCallbackRefundDto;
import com.yhsoft.wxprogram.service.WechatRefundCallback;
import com.yhsoft.wxprogram.utils.AesUtil;
import com.yhsoft.wxprogram.utils.ConstantPropertiesUtils;
import com.yhsoft.wxprogram.utils.WxPayRefundCallbackUtil;
import io.swagger.annotations.Api;
import com.alibaba.druid.support.json.JSONUtils;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.entity.ContentType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * @author: yyyyyyyh
 * @create: 2023-10-12
 * @Version 1.0
 **/
@Slf4j
@Api(tags = {"G-wx-支付接口"})
@RestController
@RequestMapping("/wxApi/pay/")
public class WxPayController {

    @Autowired
    private IBuyerOrderService iBuyerOrderService;

    @Autowired
    private IBuyerPaymentService iBuyerPaymentService;

    @Resource
    private Verifier verifier;


    @ApiOperation("付款订单的预支付会话标识")
    @GetMapping("/prepay")
    public Result<?> prepay(@RequestParam String orderId) {
        Map<String, String> map = iBuyerPaymentService.prepay(orderId);
        return Result.success(map);
    }

    @ApiOperation("微信支付查询订单接口")
    //查询订单支付状态
    @GetMapping("/queryPayStatus")
    public Result<?> queryPayStatus(@RequestParam("orderId") String orderId) {
        //1. 调用微信支付系统接口查询订单支付状态
        Map<String, String> resultMap = iBuyerPaymentService.queryPayStatus(orderId);

        //2. 微信支付系统返回值为null，支付失败
        if (resultMap == null) {
            return Result.fail("支付失败");
        }

        //3. 根据返回值，判断是否支付成功
        String result = iBuyerOrderService.paySuccess(resultMap);
        return result.contains("支付成功") ? Result.success("支付成功") : Result.fail(result);

    }

    @ApiOperation("微信付款成功或失败回调接口")
    @PostMapping("/callback")
    public Result<?> callback(HttpServletRequest request, HttpServletResponse response) throws Exception {
        //读取数据
        String body = readData(request);
        log.info("支付成功回调：{}", body);

        //数据解密
        String plainText = decryptData(body);
        log.info("解密后的文本：{}", plainText);

        JSONObject jsonObject = JSON.parseObject(plainText);
        String outTradeNo = jsonObject.getString("out_trade_no");//商户平台订单号
        String transactionId = jsonObject.getString("transaction_id");//微信支付交易号

        log.info("商户平台订单号：{}", outTradeNo);
        log.info("微信支付交易号：{}", transactionId);

        //业务处理，修改订单状态、来单提醒
        iBuyerOrderService.paySuccess(outTradeNo, transactionId);

        //给微信响应
        responseToWeixin(response);
        return Result.success("");
    }

    @GetMapping("/refund")
    @ApiOperation("订单退款，拼接订单id")
    public Result<?> orderRefund(@RequestParam String orderNo) {
        return iBuyerPaymentService.orderRefund(orderNo);
    }

    @GetMapping("/refund/query")
    @ApiOperation("查询单笔退款（通过商户退款单号）")
    public Result<?> refundResult(@RequestParam String orderNo) {
        Map<String, Object> resultMap = iBuyerPaymentService.queryRefundStatus(orderNo);
        if (resultMap == null) {
            return Result.fail("退款失败");
        }
        String result = iBuyerOrderService.refundSuccess(resultMap);
        switch ( result) {
            case "SUCCESS":
                return Result.success("退款成功");
            case "PROCESSING":
                return Result.success("退款处理中，金额将会在24小时返还原账户");
            default:
                return Result.fail("退款失败！");
        }
    }

    @ApiOperation("微信退款回调接口")
    @PostMapping("/refundWechatCallback")
    public String refundWechatCallback(HttpServletRequest request, HttpServletResponse response) {
        return WxPayRefundCallbackUtil.wxPayRefundCallback(request, response, verifier,
                new WechatRefundCallback() {
                    @Override
                    public void success(WxChatCallbackRefundDto refundData) {
                        // TODO 退款成功的业务逻辑，例如更改订单状态为退款成功等
                        BuyerOrder one = iBuyerOrderService.getOne(Wrappers.<BuyerOrder>lambdaQuery()
                                .eq(BuyerOrder::getOrderId, refundData.getOrderId()));
                        one.setOrderStatus(7);
                        iBuyerOrderService.updateById(one);
                    }

                    @Override
                    public void fail(WxChatCallbackRefundDto refundData) {
                        // TODO 特殊情况下退款失败业务处理，例如银行卡冻结需要人工退款，此时可以邮件或短信提醒管理员，并携带退款单号等关键信息
                        System.out.println("退款失败");
                    }
                });
    }

    //读取数据
    private String readData(HttpServletRequest request) throws Exception {
        BufferedReader reader = request.getReader();
        StringBuilder result = new StringBuilder();
        String line = null;
        while ((line = reader.readLine()) != null) {
            if (result.length() > 0) {
                result.append("\n");
            }
            result.append(line);
        }
        return result.toString();
    }

    //数据解密
    private String decryptData(String body) throws Exception {
        JSONObject resultObject = JSON.parseObject(body);
        JSONObject resource = resultObject.getJSONObject("resource");
        String ciphertext = resource.getString("ciphertext");
        String nonce = resource.getString("nonce");
        String associatedData = resource.getString("associated_data");
        String apiv3KEY = ConstantPropertiesUtils.APIV3KEY;
        AesUtil aesUtil = new AesUtil(apiv3KEY.getBytes(StandardCharsets.UTF_8));
        //密文解密

        return aesUtil.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8),
                nonce.getBytes(StandardCharsets.UTF_8),
                ciphertext);
    }

    //给微信响应
    private void responseToWeixin(HttpServletResponse response) throws Exception {
        response.setStatus(200);
        HashMap<Object, Object> map = new HashMap<>();
        map.put("code", "SUCCESS");
        map.put("message", "SUCCESS");
        response.setHeader("Content-type", ContentType.APPLICATION_JSON.toString());
        response.getOutputStream().write(JSONUtils.toJSONString(map).getBytes(StandardCharsets.UTF_8));
        response.flushBuffer();
    }

    @ApiOperation("福利卡支付接口")
    @PostMapping("/flkpay")
    public Result<?> flkpay(@RequestBody FlkPayInVo inVo) throws IOException {
        log.info("福利卡支付接口参数：{}", inVo);
        String result = iBuyerOrderService.flkpay(inVo);
        if (result.contains("success")) {
            if (result.equals("success")) {
                return Result.success("支付成功！");
            } else {
                String[] a = result.split(",");
                String payablePrice = a[1];
                return Result.success(new FLKPayOutVo(payablePrice), "福利卡支付成功！还需现金支付。");
            }
        }
        return Result.fail("支付失败！" + result);
    }

}
